home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / as03.arc / PRINT.ASM < prev    next >
Assembly Source File  |  1985-08-06  |  48KB  |  1,645 lines

  1. ;MS-DOS PRINT program for background printing of text files to the list
  2. ;        device.  INT 28H is a software interrupt generated by the  DOS
  3. ;        in  its  I/O  wait  loops.   This spooler can be assembled for
  4. ;        operation using only this interrupt  which  is  portable  from
  5. ;        system to  system.  It may also be assembled to use a hardware
  6. ;        timer interrupt in addition to  the  software  INT  28H.   The
  7. ;        purpose  of  using hardware interrupts is to allow printing to
  8. ;        continue during programs which do not  enter  the  system  and
  9. ;        therefore causes the INT 28H to go away.  A timer interrupt is
  10. ;        chosen in preference to a  "printer  buffer  empty"  interrupt
  11. ;        because  PRINT  in the timer form is generic.  It can be given
  12. ;        the name of any currently installed character  device  as  the
  13. ;        "printer",  this  makes  it  portable  to  devices  which  are
  14. ;        installed by the user even in the hardware case.  It could  be
  15. ;        modified to use a buffer empty interrupt (no code is given for
  16. ;        this case), if this is done the PROMPT and BADMES messages and
  17. ;        their associated  code should be removed as PRINT will then be
  18. ;        device specific.
  19. ;
  20. ;  VERSION      1.00    07/03/82
  21.  
  22.  
  23. FALSE   EQU     0
  24. TRUE    EQU     NOT FALSE
  25.  
  26. IBM     EQU     FALSE
  27. IBMVER  EQU     IBM
  28. MSVER   EQU     TRUE
  29.  
  30.         IF      MSVER
  31. HARDINT EQU     FALSE           ;No hardware ints
  32. AINT    EQU     FALSE           ;No need to do interrupt acknowledge
  33.         ENDIF
  34.  
  35.         IF      IBM
  36. HARDINT EQU     TRUE
  37. INTLOC  EQU     1CH             ;Hardware interrupt location (Timer)
  38. AINT    EQU     TRUE            ;Acknowledge interrupts
  39. EOI     EQU     20H             ;End Of Interrupt "instruction"
  40. AKPORT  EQU     20H             ;Interrupt Acknowledge port
  41.         ENDIF
  42.  
  43. ;The following values have to do with the ERRCNT variable and the
  44. ;  CNTMES message. The values define levels at wich it is assumed
  45. ;  an off-line error exists. ERRCNT1 defines the value of ERRCNT above
  46. ;  which the CNTMES message is printed by the transient. ERRCNT2
  47. ;  defines the value of ERRCNT above which the resident will give up
  48. ;  trying to print messages on the printer, it is much greater than
  49. ;  ERRCNT1 because a much tighter loop is involved. The bounding event
  50. ;  which determines the correct value is the time required to do a
  51. ;  form feed.
  52.  
  53.         IF      IBM
  54. ERRCNT1 EQU     1000
  55. ERRCNT2 EQU     20000
  56.         ELSE
  57. ERRCNT1 EQU     1000
  58. ERRCNT2 EQU     20000
  59.         ENDIF
  60.  
  61.         IF      HARDINT
  62. TIMESLICE EQU   8               ;The PRINT scheduling time slice. PRINT
  63.                                 ; lets this many "ticks" go by before
  64.                                 ; using a time slice to pump out characters.
  65.                                 ; Setting this to 3 for instance means PRINT
  66.                                 ; Will skip 3 slices, then take the fourth.
  67.                                 ; Thus using up 1/4 of the CPU. Setting it
  68.                                 ; to one gives PRINT 1/2 of the CPU.
  69.                                 ; The above examples assume MAXTICK is
  70.                                 ; 1. The actual PRINT CPU percentage is
  71.                                 ; (MAXTICK/(1+TIMESLICE))*100
  72.  
  73. MAXTICK EQU     2               ;The PRINT in timeslice. PRINT will pump
  74.                                 ; out characters for this many clock ticks
  75.                                 ; and then exit. The selection of a value
  76.                                 ; for this is dependent on the timer rate.
  77.  
  78. BUSYTICK EQU    1               ;If PRINT sits in a wait loop waiting for
  79.                                 ; output device to come ready for this
  80.                                 ; many ticks, it gives up its time slice.
  81.                                 ; Setting it greater than or equal to
  82.                                 ; MAXTICK causes it to be ignored.
  83.  
  84. ;User gets TIMESLICE ticks and then PRINT takes MAXTICK ticks unless BUSYTICK
  85. ;       ticks go by without getting a character out.
  86.         ENDIF
  87.  
  88.  
  89. ;WARNING DANGER WARNING:
  90. ;   PRINT is a systems utility. It is clearly understood that it may have
  91. ;   to be entirely re-written for future versions of MS-DOS. The following
  92. ;   TWO vectors are version specific, they may not exist at all in future
  93. ;   versions. If they do exist, they may function differently.
  94. ; ANY PROGRAM WHICH IMITATES PRINTS USE OF THESE VECTORS IS ALSO A SYSTEMS
  95. ; UTILITY AND IS THEREFORE NOT VERSION PORTABLE IN ANY WAY SHAPE OR FORM.
  96. ; YOU HAVE BEEN WARNED, "I DID IT THE SAME WAY PRINT DID" IS NOT AN REASON
  97. ; TO EXPECT A PROGRAM TO WORK ON FUTURE VERSIONS OF MS-DOS.
  98. SOFTINT EQU     28H             ;Software interrupt generated by DOS
  99. COMINT  EQU     2FH             ;Communications interrupt used by PRINT
  100.                                 ;  This vector number is DOS reserved. It
  101.                                 ;  is not generally available to programs
  102.                                 ;  other than PRINT.
  103.  
  104. BLKSIZ  EQU     512             ;Size of the PRINT I/O block in bytes
  105. FCBSIZ  EQU     40              ;Size of an FCB
  106.  
  107.         INCLUDE DOST:DOSSYM.ASM
  108.  
  109. FCB     EQU     5CH
  110. PARMS   EQU     80H
  111.  
  112. DG      GROUP   CODE,DATA
  113.  
  114. CODE    SEGMENT
  115. ASSUME  CS:DG
  116.  
  117.         ORG     100H
  118. START:
  119.         JMP     TRANSIENT
  120.  
  121. HEADER  DB      "Vers 1.00"
  122.  
  123.         DB      128 DUP (?)
  124. ISTACK  LABEL   WORD            ;Stack starts here and grows down
  125.  
  126. ;Resident data
  127.  
  128.         IF      HARDINT
  129. INDOS   DD      ?               ;DOS buisy flag
  130. NEXTINT DD      ?               ;Chain for int
  131. BUSY    DB      0               ;Internal ME flag
  132. SOFINT  DB      0               ;Internal ME flag
  133. TICKCNT DB      0               ;Tick counter
  134. TICKSUB DB      0               ;Tick miss counter
  135. SLICECNT DB     TIMESLICE       ;Time slice counter
  136.         ENDIF
  137.  
  138. CBUSY   DB      0               ;ME on com interrupt
  139. SPNEXT  DD      ?               ;Chain location for INT 28
  140. PCANMES DB      0               ;Cancel message flag
  141. SSsave  DW      ?               ;Stack save area for INT 24
  142. SPsave  DW      ?
  143. DMAADDR DD      ?               ;Place to save DMA address
  144. HERRINT DD      ?               ;Place to save Hard error interrupt
  145. LISTDEV DD      ?               ;Pointer to Device
  146. COLPOS  DB      0               ;Column position for TAB processing
  147. NXTCHR  DW      OFFSET DG:BUFFER + BLKSIZ     ;Buffer pointer
  148. CURRFIL DW      OFFSET DG:SPLFCB    ;Current file being printed
  149.  
  150. LASTFCB DW      ?               ;Back pointer
  151. LASTFCB2 DW     ?               ;Another back pointer
  152. PABORT  DB      0               ;Abort flag
  153.  
  154. ;Resident messages
  155.  
  156. ERRMES  DB      13,10,13,10,"**********",13,10,"$"
  157. ERRMEST DB      " error reading file",13,10
  158. EMFILNAM DB     " :        .   "
  159. BELMES  DB     13,0CH,7,"$"
  160.  
  161. CANMES  DB      13,10,13,10
  162. CANFILNAM DB    " :        .   "
  163.         DB      " Canceled by operator$"
  164.  
  165. ALLCAN  DB      13,10,13,10,"All files canceled by operator$"
  166.  
  167. MESBAS  DW      OFFSET DG:ERR0
  168.         DW      OFFSET DG:ERR1
  169.         DW      OFFSET DG:ERR2
  170.         DW      OFFSET DG:ERR3
  171.         DW      OFFSET DG:ERR4
  172.         DW      OFFSET DG:ERR5
  173.         DW      OFFSET DG:ERR6
  174.         DW      OFFSET DG:ERR7
  175.         DW      OFFSET DG:ERR8
  176.         DW      OFFSET DG:ERR9
  177.         DW      OFFSET DG:ERR10
  178.         DW      OFFSET DG:ERR11
  179.         DW      OFFSET DG:ERR12
  180.  
  181. ;INT 24 messages A La COMMAND
  182.  
  183. ERR0    DB      "Write protect$"
  184. ERR1    DB      "Bad unit$"
  185. ERR2    DB      "Not ready$"
  186. ERR3    DB      "Bad command$"
  187. ERR4    DB      "Data$"
  188. ERR5    DB      "Bad call format$"
  189. ERR6    DB      "Seek$"
  190. ERR7    DB      "Non-DOS disk$"
  191. ERR8    DB      "Sector not found$"
  192. ERR9    DB      "No paper$"
  193. ERR10   DB      "Write fault$"
  194. ERR11   DB      "Read fault$"
  195. ERR12   DB      "Disk$"
  196.  
  197. FATMES  DB     "File allocation table bad drive "
  198. BADDRVM DB     "A.",13,10,"$"
  199.  
  200. ;The DATA buffer
  201. BUFFER  DB      BLKSIZ DUP(0)
  202.         DB      ?
  203. CODE    ENDS
  204.  
  205. ;Transient data
  206.  
  207. DATA    SEGMENT BYTE
  208.         ORG     0
  209. SWITCHAR DB     ?               ;User switch character
  210. FULLFLAG DB     0               ;Flag for printing queue full message
  211. MAKERES DB      0               ;Flag to indicate presence of resident
  212. ARGSETUP DB     0               ;Flag to indicate a formatted FCB exists at 5C
  213. DEFDRV  DB      0               ;Default drive
  214. CANFLG  DB      0               ;Flag to indicate cancel
  215. FILCNT  DB      0               ;Number of files
  216. SPLIST  DD      ?               ;Pointer to FCBs in resident
  217. CURFILE DD      ?               ;Pointer to current FCB
  218. SRCHFCB DB      38 DUP (0)      ;SEARCH-FIRST/NEXT FCB
  219. ENDRES  DW      OFFSET DG:DEF_ENDRES    ;Term-Res location
  220.  
  221. ;Messages
  222.  
  223. NOFILS  DB      "PRINT queue is empty",13,10,"$"
  224. CURMES  DB      13,10,"        "
  225. CURFNAM DB      " :        .    is currently being printed",13,10,"$"
  226. FILMES  DB      "        "
  227. FILFNAM DB      " :        .    is in queue"
  228. CRLF    DB      13,10,"$"
  229. OPMES    DB     "Cannot open "
  230. OPFILNAM DB     " :        .    ",13,10,"$"
  231. FULLMES DB      "PRINT queue is full",13,10,"$"
  232. SRCHMES LABEL   BYTE
  233. SRCHFNAM DB     " :        .    "," File not found",13,10,"$"
  234. BADMES  DB      "List output is not assigned to a device",13,10,"$"
  235. GOODMES DB      "Resident part of PRINT installed",13,10,"$"
  236. PROMPT  DB      "Name of list device [PRN]: $"
  237. CNTMES  DB      "Errors on list device indicate that it",13,10
  238.         DB      "may be off-line. Please check it.",13,10,13,10,"$"
  239. BADSWT  DB      "Invalid parameter",13,10,"$"
  240.  
  241.  
  242. BADVER  DB      "Incorrect DOS version",13,10,"$"
  243.  
  244.         IF      IBM
  245. ;Reserved names for parallel card
  246. INT_17_HITLIST LABEL BYTE
  247.         DB      8,"PRN     ",0
  248.         DB      8,"LPT1    ",0
  249.         DB      8,"LPT2    ",1
  250.         DB      8,"LPT3    ",2
  251.         DB      0
  252. ;Reserved names for Async adaptor
  253. INT_14_HITLIST  LABEL BYTE
  254.         DB      8,"AUX     ",0
  255.         DB      8,"COM1    ",0
  256.         DB      8,"COM2    ",1
  257.         DB      0
  258.         ENDIF
  259.  
  260. COMBUF  DB      14,0            ;Device name buffer
  261.         DB      14 DUP (?)
  262. LISTFCB DB      0,"PRN        " ;Device name FCB
  263.         DB      25 DUP (0)
  264. PARSEBUF DB     80 DUP (?)      ;Parsing space
  265.  
  266. DATA    ENDS
  267.  
  268. CODE    SEGMENT
  269. ASSUME  CS:DG,DS:DG,ES:DG,SS:DG
  270.  
  271.  
  272. ;Interrupt routines
  273. ASSUME  CS:DG,DS:NOTHING,ES:NOTHING,SS:NOTHING
  274.         IF      HARDINT
  275. HDSPINT:                        ;Hardware interrupt entry point
  276.         INC     [TICKCNT]       ;Tick
  277.         INC     [TICKSUB]       ;Tick
  278.         CMP     [SLICECNT],0
  279.         JZ      TIMENOW
  280.         DEC     [SLICECNT]      ;Count down
  281.         JMP     SHORT CHAININT  ;Not time yet
  282. TIMENOW:
  283.         CMP     [BUSY],0        ;See if interrupting ourself
  284.         JNZ     CHAININT
  285.         PUSH    DS
  286.         PUSH    SI
  287.         LDS     SI,[INDOS]      ;Check for making DOS calls
  288.         CMP     BYTE PTR [SI],0
  289.         POP     SI
  290.         POP     DS
  291.         JNZ     CHAININT        ;DOS is Buisy
  292.         INC     [BUSY]          ;Exclude furthur interrupts
  293.         MOV     [TICKCNT],0     ;Reset tick counter
  294.         MOV     [TICKSUB],0     ;Reset tick counter
  295.         STI                     ;Keep things rolling
  296.  
  297.         IF      AINT
  298.         MOV     AL,EOI          ;Acknowledge interrupt
  299.         OUT     AKPORT,AL
  300.         ENDIF
  301.  
  302.         CALL    DOINT
  303.         CLI
  304.         MOV     [SLICECNT],TIMESLICE    ;Either soft or hard int resets time slice
  305.         MOV     [BUSY],0        ;Done, let others in
  306. CHAININT:
  307.         JMP     [NEXTINT]       ;Chain to next clock routine
  308.         ENDIF
  309.  
  310.  
  311. SPINT:                          ;INT 28H entry point
  312.         IF      HARDINT
  313.         CMP     [BUSY],0
  314.         JNZ     NXTSP
  315.         INC     [BUSY]          ;Exclude hardware interrupt
  316.         INC     [SOFINT]        ;Indicate a software int in progress
  317.         ENDIF
  318.  
  319.         STI                     ;Hardware interrupts ok on INT 28H entry
  320.         CALL    DOINT
  321.  
  322.         IF      HARDINT
  323.         CLI
  324.         MOV     [SOFINT],0      ;Indicate INT done
  325.         MOV     [SLICECNT],TIMESLICE    ;Either soft or hard int resets time slice
  326.         MOV     [BUSY],0
  327.         ENDIF
  328.  
  329. NXTSP:  JMP     [SPNEXT]        ;Chain to next INT 28
  330.  
  331. DOINT:
  332.         PUSH    SI
  333.         MOV     SI,[CURRFIL]
  334.         INC     SI
  335.         INC     SI
  336.         CMP     BYTE PTR CS:[SI],-1
  337.         POP     SI
  338.         JNZ     GOAHEAD
  339.         JMP     SPRET           ;Nothing to do
  340. GOAHEAD:
  341.         PUSH    AX              ;Need a working register
  342.         MOV     [SSsave],SS
  343.         MOV     [SPsave],SP
  344.         MOV     AX,CS
  345.         CLI
  346. ;Go to internal stack to prevent INT 24 overflowing system stack
  347.         MOV     SS,AX
  348.         MOV     SP,OFFSET DG:ISTACK
  349.         STI
  350.         PUSH    ES
  351.         PUSH    DS
  352.         PUSH    BX
  353.         PUSH    CX
  354.         PUSH    DX
  355.         PUSH    SI
  356.         PUSH    DI
  357.         PUSH    CS
  358.         POP     DS
  359. ASSUME  DS:DG
  360.  
  361.         MOV     BX,[NXTCHR]
  362.         CMP     BX,OFFSET DG:BUFFER + BLKSIZ
  363.         JNZ     PLOOP
  364.         JMP     READBUFF                ;Buffer empty
  365.  
  366. PLOOP:
  367.         IF      HARDINT
  368.         MOV     BX,[NXTCHR]
  369.         CMP     BX,OFFSET DG:BUFFER + BLKSIZ
  370.         JZ      DONEJMP                 ;Buffer has become empty
  371.         CMP     [SOFINT],0
  372.         JNZ     STATCHK
  373.         CMP     [TICKCNT],MAXTICK       ;Check our time slice
  374.         JAE     DONEJMP
  375. STATCHK:
  376.         ENDIF
  377.  
  378.         CALL    PSTAT
  379.  
  380.         IF      HARDINT
  381.         JZ      DOCHAR                  ;Printer ready
  382.         CMP     [SOFINT],0
  383.         ENDIF
  384.  
  385.         JNZ     DONEJMP                 ;If soft int give up
  386.  
  387.         IF      HARDINT
  388.         CMP     [TICKSUB],BUSYTICK      ;Check our busy timeout
  389.         JAE     DONEJMP
  390.         JMP     PLOOP
  391.         ENDIF
  392.  
  393. DOCHAR:
  394.         MOV     AL,BYTE PTR [BX]
  395.         CMP     AL,1AH                  ;^Z?
  396.         JZ      FILEOFJ                 ;CPM EOF
  397.         CMP     AL,0DH                  ;CR?
  398.         JNZ     NOTCR
  399.         MOV     [COLPOS],0
  400. NOTCR:
  401.         CMP     AL,9                    ;TAB?
  402.         JNZ     NOTABDO
  403.         MOV     CL,[COLPOS]
  404.         OR      CL,0F8H
  405.         NEG     CL
  406.         XOR     CH,CH
  407.         JCXZ    TABDONE
  408. TABLP:
  409.         MOV     AL," "
  410.         INC     [COLPOS]
  411.         PUSH    CX
  412.         CALL    POUT
  413.         POP     CX
  414.         LOOP    TABLP
  415.         JMP     TABDONE
  416.  
  417. NOTABDO:
  418.         CMP     AL,8                    ;Back space?
  419.         JNZ     NOTBACK
  420.         DEC     [COLPOS]
  421. NOTBACK:
  422.         CMP     AL,20H                  ;Non Printing char?
  423.         JB      NOCHAR
  424.         INC     [COLPOS]                ;Printing char
  425. NOCHAR:
  426.         CALL    POUT                    ;Print it
  427. TABDONE:
  428.         INC     [NXTCHR]                ;Next char
  429.  
  430.         IF      HARDINT
  431.         MOV     [TICKSUB],0             ;Got a character out, Reset counter
  432.         CMP     [SOFINT],0              ;Soft int does one char at a time
  433.         JZ      PLOOP
  434.         ENDIF
  435.  
  436. DONEJMP:
  437.         POP     DI
  438.         POP     SI
  439.         POP     DX
  440.         POP     CX
  441.         POP     BX
  442.         POP     DS
  443.         POP     ES
  444. ASSUME  DS:NOTHING,ES:NOTHING
  445.         CLI
  446.         MOV     SS,[SSsave]             ;Restore Entry Stack
  447.         MOV     SP,[SPsave]
  448.         STI
  449.         POP     AX
  450. SPRET:
  451.         RET
  452.  
  453. FILEOFJ: JMP    FILEOF
  454.  
  455. READBUFF:
  456. ASSUME  DS:DG,ES:NOTHING
  457.  
  458.         MOV     AL,24H
  459.         MOV     AH,GET_INTERRUPT_VECTOR
  460.         INT     21H
  461.         MOV     WORD PTR [HERRINT+2],ES         ;Save current vector
  462.         MOV     WORD PTR [HERRINT],BX
  463.         MOV     DX,OFFSET DG:DSKERR
  464.         MOV     AL,24H
  465.         MOV     AH,SET_INTERRUPT_VECTOR         ;Install our own
  466.         INT     21H             ;Spooler must catch its errors
  467.         MOV     AH,GET_DMA
  468.         INT     21H
  469.         MOV     WORD PTR [DMAADDR+2],ES         ;Save DMA address
  470.         MOV     WORD PTR [DMAADDR],BX
  471.         MOV     DX,OFFSET DG:BUFFER
  472.         MOV     AH,SET_DMA
  473.         INT     21H             ;New DMA address
  474.         MOV     [PABORT],0      ;No abort
  475.         MOV     DX,[CURRFIL]    ;Read
  476.         INC     DX
  477.         INC     DX              ;Skip over pointer
  478.         MOV     AH,FCB_SEQ_READ
  479.         INT     21H
  480.         PUSH    AX
  481.         LDS     DX,[DMAADDR]
  482. ASSUME  DS:NOTHING
  483.         MOV     AH,SET_DMA
  484.         INT     21H             ;Restore DMA
  485.         LDS     DX,[HERRINT]
  486.         MOV     AL,24H
  487.         MOV     AH,SET_INTERRUPT_VECTOR
  488.         INT     21H             ;Restore Error INT
  489.         POP     AX
  490.         PUSH    CS
  491.         POP     DS
  492. ASSUME  DS:DG
  493.         CMP     [PABORT],0
  494.         JNZ     TONEXTFIL       ;Barf on this file, got INT 24
  495.         CMP     AL,01
  496.         JZ      FILEOF          ;Read EOF?
  497.         MOV     BX,OFFSET DG:BUFFER     ;Buffer full
  498.         MOV     [NXTCHR],BX
  499.         JMP     DONEJMP
  500.  
  501. FILEOF:
  502.         MOV     AL,0CH          ;Form feed
  503.         CALL    LOUT
  504. TONEXTFIL:
  505.         CALL    NEXTFIL
  506.         JMP     DONEJMP
  507.  
  508. ;INT 24 handler
  509.  
  510. DSKERR:
  511. ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING
  512.         STI
  513.         CMP     [PABORT],0
  514.         JNZ     IGNRET
  515.         PUSH    BX
  516.         PUSH    CX
  517.         PUSH    DX
  518.         PUSH    DI
  519.         PUSH    SI
  520.         PUSH    BP
  521.         PUSH    ES
  522.         PUSH    DS
  523.         PUSH    CS
  524.         POP     DS
  525.         PUSH    CS
  526.         POP     ES
  527. ASSUME  DS:DG,ES:DG
  528.         ADD     [BADDRVM],AL    ;Set correct drive letter
  529.         MOV     SI,OFFSET DG:ERRMES
  530.         CALL    LISTMES
  531.         TEST    AH,080H
  532.         JNZ     FATERR
  533.         AND     DI,0FFH
  534.         CMP     DI,12
  535.         JBE     HAVCOD
  536.         MOV     DI,12
  537. HAVCOD:
  538.         SHL     DI,1
  539.         MOV     DI,WORD PTR [DI+MESBAS] ; Get pointer to error message
  540.         MOV     SI,DI
  541.         CALL    LISTMES          ; Print error type
  542.         MOV     DI,OFFSET DG:EMFILNAM
  543.         MOV     SI,[CURRFIL]
  544.         ADD     SI,2             ;Get to file name
  545.         LODSB
  546.         ADD     AL,'@'
  547.         STOSB
  548.         INC     DI
  549.         MOV     CX,4
  550.         REP     MOVSW
  551.         INC     DI
  552.         MOVSW
  553.         MOVSB
  554.         MOV     SI,OFFSET DG:ERRMEST
  555.         CALL    LISTMES
  556. SETABORT:
  557.         INC     [PABORT]                ;Indicate abort
  558.         POP     DS
  559.         POP     ES
  560.         POP     BP
  561.         POP     SI
  562.         POP     DI
  563.         POP     DX
  564.         POP     CX
  565.         POP     BX
  566. IGNRET:
  567.         XOR     AL,AL                   ;Ignore
  568.         IRET
  569.  
  570. FATERR:
  571.         MOV     SI,OFFSET DG:FATMES
  572.         CALL    LISTMES
  573.         JMP     SHORT SETABORT
  574.  
  575. ADDFILJ: JMP    ADDFIL
  576.  
  577. COMBUSY:
  578.         MOV     AX,-1
  579.         IRET
  580.  
  581. ;Communications interrupt
  582. SPCOMINT:
  583. ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING
  584.         CMP     [CBUSY],0
  585.         JNZ     COMBUSY
  586.         INC     [CBUSY]                 ;Exclude
  587.         STI                             ;Turn ints back on
  588.         PUSH    SI
  589.         PUSH    DI
  590.         PUSH    CX
  591.         PUSH    DS
  592.         PUSH    CS
  593.         POP     DS
  594. ASSUME  DS:DG
  595.         MOV     [PCANMES],0             ;Havn't printed cancel message
  596.         OR      AH,AH
  597.         JZ      ADDFILJ                 ;Add file
  598.         CMP     AH,1
  599.         JZ      CANFIL                  ;Cancel File(s)
  600.         XOR     AL,AL
  601. SETCOUNT:
  602.         PUSH    AX              ;Save AL return code
  603.         XOR     AH,AH
  604.         MOV     SI,OFFSET DG:SPLFCB
  605.         MOV     CX,[NUMFCBS]
  606. CNTFILS:
  607.         CMP     BYTE PTR [SI+2],-1        ;Valid?
  608.         JZ      LNEXT
  609.         INC     AH
  610. LNEXT:
  611.         ADD     SI,FCBSIZ
  612.         LOOP    CNTFILS
  613. COMRET:
  614.         MOV     BX,OFFSET DG:SPLFCB
  615.         MOV     DX,[CURRFIL]
  616.         PUSH    DS
  617.         POP     ES
  618. ASSUME  ES:NOTHING
  619.         MOV     CH,AH
  620.         POP     AX                      ;Get AL return
  621.         MOV     AH,CH
  622.  
  623.         IF      HARDINT
  624. BWAIT3:
  625.         CMP     [BUSY],0
  626.         JNZ     BWAIT3
  627.         INC     [BUSY]
  628.         ENDIF
  629.  
  630.         CALL    PSTAT                   ; Tweek error counter
  631.  
  632.         IF      HARDINT
  633.         MOV     [BUSY],0
  634.         ENDIF
  635.  
  636.         POP     DS
  637. ASSUME  DS:NOTHING
  638.         POP     CX
  639.         POP     DI
  640.         POP     SI
  641.         MOV     [CBUSY],0
  642.         IRET
  643.  
  644. DELALLJ: JMP    DELALL
  645.  
  646. CANFIL:
  647. ASSUME  DS:DG,ES:NOTHING
  648.         MOV     CX,[NUMFCBS]
  649.  
  650.         IF      HARDINT
  651. BWAIT:
  652.         CMP     [BUSY],0
  653.         JNZ     BWAIT
  654.         INC     [BUSY]
  655.         ENDIF
  656.  
  657.         MOV     SI,[CURRFIL]
  658.         CMP     DX,-1
  659.         JZ      DELALLJ
  660.         MOV     BX,[SI]
  661.         PUSH    BX
  662. LOOKEND:                        ;Set initial pointer values
  663.         CMP     BX,SI
  664.         JZ      GOTLAST
  665.         POP     AX
  666.         PUSH    BX
  667.         MOV     BX,[BX]
  668.         JMP     SHORT LOOKEND
  669.  
  670. GOTLAST:
  671.         POP     BX
  672.         MOV     [LASTFCB],BX
  673.         MOV     [LASTFCB2],BX
  674.         POP     ES
  675.         PUSH    ES
  676.         MOV     BX,SI
  677. LOOKMATCH:
  678.         MOV     DI,DX
  679.         ADD     SI,2                    ;Skip pointer
  680.         CMP     BYTE PTR [SI],-1
  681.         JZ      CANTERMJ                ;No more
  682.         CMPSB
  683.         JNZ     SKIPFIL                 ;DRIVE
  684.         PUSH    CX
  685.         MOV     CX,11
  686. NXTCHAR:
  687.         MOV     AL,ES:[DI]
  688.         INC     DI
  689.         CALL    UPCONV
  690.         MOV     AH,AL
  691.         LODSB
  692.         CALL    UPCONV
  693.         CMP     AH,"?"                  ;Wild card?
  694.         JZ      NXTCHRLP                ;Yes
  695.         CMP     AH,AL
  696.         JNZ     SKIPFILC
  697. NXTCHRLP:
  698.         LOOP    NXTCHAR
  699. MATCH:
  700.         POP     CX
  701.         MOV     AH,-1
  702.         XCHG    AH,[BX+2]               ;Zap it
  703.         CMP     BX,[CURRFIL]            ;Is current file?
  704.         JNZ     REQUEUE                 ;No
  705.         MOV     AL,1
  706.         XCHG    AL,[PCANMES]
  707.         OR      AL,AL
  708.         JNZ     DIDCMES                 ;Only print cancel message once
  709.         PUSH    ES
  710.         PUSH    CS
  711.         POP     ES
  712.         MOV     DI,OFFSET DG:CANFILNAM
  713.         MOV     SI,BX
  714.         ADD     SI,3             ;Get to file name
  715.         MOV     AL,AH
  716.         ADD     AL,'@'
  717.         STOSB
  718.         INC     DI
  719.         MOV     CX,4
  720.         REP     MOVSW
  721.         INC     DI
  722.         MOVSW
  723.         MOVSB
  724.         POP     ES
  725.         MOV     SI,OFFSET DG:CANMES
  726.         CALL    LISTMES
  727.         MOV     SI,OFFSET DG:BELMES
  728.         CALL    LISTMES
  729. DIDCMES:
  730.         PUSH    CX
  731.         CALL    NEXTFIL
  732. SKIPFILC:
  733.         POP     CX
  734. SKIPFIL:
  735.         MOV     [LASTFCB2],BX
  736.         MOV     BX,[BX]
  737. NEXTFC:
  738.         MOV     SI,BX
  739.         LOOP    LOOKMATCH
  740. CANTERMJ: JMP   SHORT CANTERM
  741.  
  742. REQUEUE:
  743.         MOV     AX,[BX]
  744.         CMP     AX,[CURRFIL]            ;Is last FCB?
  745.         JZ      SKIPFIL                 ;Yes, is in right place
  746.         MOV     SI,[LASTFCB2]
  747.         MOV     [SI],AX                 ;Unlink FCB
  748.         MOV     SI,[CURRFIL]
  749.         MOV     [BX],SI
  750.         MOV     SI,[LASTFCB]
  751.         MOV     [SI],BX                 ;Link FCB at end
  752.         MOV     [LASTFCB],BX            ;New end
  753.         MOV     BX,AX                   ;Process what it pointed to
  754.         JMP     SHORT NEXTFC
  755.  
  756. DELALL:
  757.         CMP     BYTE PTR CS:[SI+2],-1   ;Examine current file
  758. DELALL2:
  759.         MOV     BYTE PTR [SI+2],-1      ;Zap it
  760.         MOV     SI,[SI]
  761.         LOOP    DELALL2
  762.         JZ      CANTERM1                ;No message if nothing was in progress
  763.         MOV     SI,OFFSET DG:ALLCAN
  764.         CALL    LISTMES
  765.         MOV     SI,OFFSET DG:BELMES
  766.         CALL    LISTMES
  767. CANTERM1:
  768.         MOV     [NXTCHR],OFFSET DG:BUFFER + BLKSIZ  ;Buffer empty
  769. CANTERM:
  770.  
  771.         IF      HARDINT
  772.         MOV     [BUSY],0
  773.         ENDIF
  774.  
  775.         XOR     AX,AX
  776.         JMP     SETCOUNT
  777.  
  778. UPCONV:
  779.         CMP     AL,'a'
  780.         JB      NOCONV
  781.         CMP     AL,'z'
  782.         JA      NOCONV
  783.         SUB     AL,20H
  784. NOCONV:
  785.         RET
  786.  
  787. ADDFIL:
  788. ASSUME  DS:DG,ES:NOTHING
  789.         MOV     SI,[CURRFIL]
  790.         MOV     CX,[NUMFCBS]
  791.  
  792.         IF      HARDINT
  793. BWAIT2:
  794.         CMP     [BUSY],0
  795.         JNZ     BWAIT2
  796.         INC     [BUSY]
  797.         ENDIF
  798.  
  799. LOOKSPOT:
  800.         CMP     BYTE PTR [SI+2],-1
  801.         JZ      GOTSPOT
  802.         MOV     SI,[SI]
  803.         LOOP    LOOKSPOT
  804.  
  805.         IF      HARDINT
  806.         MOV     [BUSY],0
  807.         ENDIF
  808.  
  809.         MOV     AL,1
  810.         JMP     SETCOUNT
  811.  
  812. GOTSPOT:
  813.         PUSH    DS
  814.         POP     ES
  815.         POP     DS
  816.         PUSH    DS
  817. ASSUME  DS:NOTHING
  818.         PUSH    SI
  819.         MOV     DI,SI
  820.         ADD     DI,2
  821.         MOV     SI,DX
  822.         MOV     CX,19
  823.         REP     MOVSW           ;Copy in and set FCB
  824.         POP     SI
  825.         PUSH    ES
  826.         POP     DS
  827. ASSUME  DS:DG
  828.         MOV     WORD PTR [SI+2+fcb_EXTENT],0
  829.         MOV     BYTE PTR [SI+2+fcb_NR],0
  830.         MOV     WORD PTR [SI+2+fcb_RECSIZ],BLKSIZ
  831.  
  832.         IF      HARDINT
  833.         MOV     [BUSY],0
  834.         ENDIF
  835.  
  836.         XOR     AL,AL
  837.         JMP     SETCOUNT
  838.  
  839. NEXTFIL:
  840. ASSUME  DS:DG,ES:NOTHING
  841.         MOV     SI,[CURRFIL]
  842.         MOV     BYTE PTR [SI+2],-1      ;Done with current file
  843.         MOV     SI,[SI]
  844.         MOV     [CURRFIL],SI
  845.         MOV     [NXTCHR],OFFSET DG:BUFFER + BLKSIZ  ;Buffer empty
  846.         MOV     [COLPOS],0                          ;Start of line
  847.         RET
  848.  
  849. LISTMES:
  850. ASSUME  DS:DG,ES:NOTHING
  851.         LODSB
  852.         CMP     AL,"$"
  853.         JZ      LMESDONE
  854.         CALL    LOUT
  855.         JMP     LISTMES
  856.  
  857. LMESDONE:
  858.         RET
  859.  
  860. LOUT:
  861.         PUSH    BX
  862. LWAIT:
  863.         CALL    PSTAT
  864.         JZ      PREADY
  865.         CMP     [ERRCNT],ERRCNT2
  866.         JA      POPRET                  ;Don't get stuck
  867.         JMP     SHORT LWAIT
  868. PREADY:
  869.         CALL    POUT
  870. POPRET:
  871.         POP     BX
  872.         RET
  873.  
  874. ;Stuff for BIOS interface
  875. IOBUSY  EQU     0200H
  876. IOERROR EQU     8000H
  877.  
  878. BYTEBUF DB      ?
  879.  
  880. CALLAD  DD      ?
  881.  
  882. IOCALL  DB      22
  883.         DB      0
  884. IOREQ   DB      ?
  885. IOSTAT  DW      0
  886.         DB      8 DUP(?)
  887.         DB      0
  888.         DW      OFFSET DG:BYTEBUF
  889. INTSEG  DW      ?
  890. IOCNT   DW      1
  891.         DW      0
  892.  
  893. PSTAT:
  894. ASSUME  DS:DG
  895.         PUSH    BX
  896.         INC     [ERRCNT]
  897.         MOV     BL,10
  898.         CALL    DOCALL
  899.         TEST    [IOSTAT],IOERROR
  900.         JZ      NOSTATERR
  901.         OR      [IOSTAT],IOBUSY         ;If error, show buisy
  902. NOSTATERR:
  903.         TEST    [IOSTAT],IOBUSY
  904.         JNZ     RET13P                  ;Shows buisy
  905.         MOV     [ERRCNT],0
  906. RET13P:
  907.         POP     BX
  908.         RET
  909.  
  910. POUT:
  911. ASSUME  DS:DG
  912.         MOV     [BYTEBUF],AL
  913.         MOV     BL,8
  914. DOCALL:
  915.         PUSH    ES
  916.         MOV     [IOREQ],BL
  917.         MOV     BX,CS
  918.         MOV     ES,BX
  919.         MOV     BX,OFFSET DG:IOCALL
  920.         MOV     [IOSTAT],0
  921.         MOV     [IOCNT],1
  922.         PUSH    DS
  923.         PUSH    SI
  924.         PUSH    AX
  925.         LDS     SI,[LISTDEV]
  926. ASSUME  DS:NOTHING
  927.         MOV     AX,[SI+6]
  928.         MOV     WORD PTR [CALLAD],AX
  929.         CALL    [CALLAD]
  930.         MOV     AX,[SI+8]
  931.         MOV     WORD PTR [CALLAD],AX
  932.         CALL    [CALLAD]
  933.         POP     AX
  934.         POP     SI
  935.         POP     DS
  936. ASSUME  DS:DG
  937.         POP     ES
  938.         RET
  939.  
  940.         IF      IBM
  941. REAL_INT_13 DD  ?
  942. INT_13_RETADDR DW OFFSET DG:INT_13_BACK
  943.  
  944. INT_13  PROC    FAR
  945. ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING
  946.         PUSHF
  947.         INC     [BUSY]                  ;Exclude if dumb program call ROM
  948.         PUSH    CS
  949.         PUSH    [INT_13_RETADDR]
  950.         PUSH    WORD PTR [REAL_INT_13+2]
  951.         PUSH    WORD PTR [REAL_INT_13]
  952.         RET
  953. INT_13  ENDP
  954.  
  955. INT_13_BACK     PROC    FAR
  956.         PUSHF
  957.         DEC     [BUSY]
  958.         POPF
  959.         RET     2               ;Chuck saved flags
  960. INT_13_BACK     ENDP
  961.         ENDIF
  962.  
  963.  
  964.         IF      IBM
  965.  
  966. REAL_INT_5  DD  ?
  967. REAL_INT_17 DD  ?
  968. INT_17_NUM  DW  0
  969.  
  970. INT_17:
  971. ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING
  972.         PUSH    SI
  973.         MOV     SI,[CURRFIL]
  974.         INC     SI
  975.         INC     SI
  976.         CMP     BYTE PTR CS:[SI],-1
  977.         POP     SI
  978.         JZ      DO_INT_17               ;Nothing pending, so OK
  979.         CMP     DX,[INT_17_NUM]
  980.         JNZ     DO_INT_17               ;Not my unit
  981.         CMP     [BUSY],0
  982.         JNZ     DO_INT_17               ;You are me
  983.         STI
  984.         MOV     AH,0A1H                 ;You are bad, get out of paper
  985.         IRET
  986.  
  987. DO_INT_17:
  988.         JMP     [REAL_INT_17]           ;Do a 17
  989.  
  990. REAL_INT_14 DD  ?
  991. INT_14_NUM  DW  0
  992.  
  993. INT_14:
  994. ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING
  995.         PUSH    SI
  996.         MOV     SI,[CURRFIL]
  997.         INC     SI
  998.         INC     SI
  999.         CMP     BYTE PTR CS:[SI],-1
  1000.         POP     SI
  1001.         JZ      DO_INT_14               ;Nothing pending, so OK
  1002.         CMP     DX,[INT_14_NUM]
  1003.         JNZ     DO_INT_14               ;Not my unit
  1004.         CMP     [BUSY],0
  1005.         JNZ     DO_INT_14               ;You are me
  1006.         STI
  1007.         OR      AH,AH
  1008.         JZ      SET14_AX
  1009.         CMP     AH,2
  1010.         JBE     SET14_AH
  1011. SET14_AX:
  1012.         MOV     AL,0
  1013. SET14_AH:
  1014.         MOV     AH,80H                  ;Time out
  1015.         IRET
  1016.  
  1017. DO_INT_14:
  1018.         JMP     [REAL_INT_14]           ;Do a 14
  1019.  
  1020. INT_5:
  1021. ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING
  1022.         PUSH    SI
  1023.         MOV     SI,[CURRFIL]
  1024.         INC     SI
  1025.         INC     SI
  1026.         CMP     BYTE PTR CS:[SI],-1
  1027.         POP     SI
  1028.         JZ      DO_INT_5                ;Nothing pending, so OK
  1029.         CMP     [INT_17_NUM],0
  1030.         JNZ     DO_INT_5                ;Only care about unit 0
  1031.         IRET                            ;Pretend it worked
  1032.  
  1033. DO_INT_5:
  1034.         JMP     [REAL_INT_5]            ;Do a 5
  1035.         ENDIF
  1036.  
  1037.  
  1038. ;The following data is order and position dependant
  1039. NUMFCBS DW      10
  1040. ERRCNT  DW      0
  1041.  
  1042. SPLFCB  DW      OFFSET DG:FC1
  1043.         DB      (FCBSIZ - 2) DUP (-1)
  1044. FC1     DW      OFFSET DG:FC2
  1045.         DB      (FCBSIZ - 2) DUP (-1)
  1046. FC2     DW      OFFSET DG:FC3
  1047.         DB      (FCBSIZ - 2) DUP (-1)
  1048. FC3     DW      OFFSET DG:FC4
  1049.         DB      (FCBSIZ - 2) DUP (-1)
  1050. FC4     DW      OFFSET DG:FC5
  1051.         DB      (FCBSIZ - 2) DUP (-1)
  1052. FC5     DW      OFFSET DG:FC6
  1053.         DB      (FCBSIZ - 2) DUP (-1)
  1054. FC6     DW      OFFSET DG:FC7
  1055.         DB      (FCBSIZ - 2) DUP (-1)
  1056. FC7     DW      OFFSET DG:FC8
  1057.         DB      (FCBSIZ - 2) DUP (-1)
  1058. FC8     DW      OFFSET DG:FC9
  1059.         DB      (FCBSIZ - 2) DUP (-1)
  1060. FC9     DW      OFFSET DG:SPLFCB
  1061.         DB      (FCBSIZ - 2) DUP (-1)
  1062.  
  1063. DEF_ENDRES      LABEL   BYTE
  1064.  
  1065. ASSUME  CS:DG,DS:DG,ES:DG,SS:DG
  1066.  
  1067. BADSPOOL:
  1068.         MOV     DX,OFFSET DG:BADMES
  1069.         MOV     AH,STD_CON_STRING_OUTPUT
  1070.         INT     21H
  1071.         INT     20H
  1072.  
  1073. SETUP:
  1074. ;Called once to install resident
  1075.         CLD
  1076.         MOV     [INTSEG],CS
  1077.         MOV     DX,OFFSET DG:PROMPT
  1078.         MOV     AH,STD_CON_STRING_OUTPUT
  1079.         INT     21H
  1080.         MOV     DX,OFFSET DG:COMBUF
  1081.         MOV     AH,STD_CON_STRING_INPUT
  1082.         INT     21H                     ;Get device name
  1083.         MOV     DX,OFFSET DG:CRLF
  1084.         MOV     AH,STD_CON_STRING_OUTPUT
  1085.         INT     21H
  1086.         MOV     CL,[COMBUF+1]
  1087.         OR      CL,CL
  1088.         JZ      DEFSPOOL                ;User didn't specify one
  1089.         XOR     CH,CH
  1090.         MOV     DI,OFFSET DG:LISTFCB + 1
  1091.         MOV     SI,OFFSET DG:COMBUF + 2
  1092.         REP     MOVSB
  1093. DEFSPOOL:
  1094.         MOV     DX,OFFSET DG:LISTFCB
  1095.         MOV     AH,FCB_OPEN
  1096.         INT     21H
  1097.         OR      AL,AL
  1098.         JNZ     BADSPOOL                ;Bad
  1099.         TEST    BYTE PTR [LISTFCB.fcb_DEVID],080H
  1100.         JZ      BADSPOOL                ;Must be a device
  1101.         LDS     SI,DWORD PTR [LISTFCB.fcb_FIRCLUS]
  1102. ASSUME  DS:NOTHING
  1103.         MOV     WORD PTR [CALLAD+2],DS     ;Get I/O routines
  1104.         MOV     WORD PTR [LISTDEV+2],DS    ;Get I/O routines
  1105.         MOV     WORD PTR [LISTDEV],SI
  1106.         PUSH    CS
  1107.         POP     DS
  1108. ASSUME  DS:DG
  1109.         MOV     DX,OFFSET DG:SPINT
  1110.         MOV     AL,SOFTINT
  1111.         MOV     AH,GET_INTERRUPT_VECTOR
  1112.         INT     21H                     ;Get soft vector
  1113.         MOV     WORD PTR [SPNEXT+2],ES
  1114.         MOV     WORD PTR [SPNEXT],BX
  1115.         MOV     AL,SOFTINT
  1116.         MOV     AH,SET_INTERRUPT_VECTOR
  1117.         INT     21H                     ;Set soft vector
  1118.         MOV     DX,OFFSET DG:SPCOMINT
  1119.         MOV     AL,COMINT
  1120.         MOV     AH,SET_INTERRUPT_VECTOR              ;Set communication vector
  1121.         INT     21H
  1122.  
  1123.         IF      IBM
  1124.         MOV     AL,13H
  1125.         MOV     AH,GET_INTERRUPT_VECTOR
  1126.         INT     21H
  1127.         MOV     WORD PTR [REAL_INT_13+2],ES
  1128.         MOV     WORD PTR [REAL_INT_13],BX
  1129.         MOV     DX,OFFSET DG:INT_13
  1130.         MOV     AL,13H
  1131.         MOV     AH,SET_INTERRUPT_VECTOR
  1132.         INT     21H             ;Set diskI/O interrupt
  1133.         MOV     AL,17H
  1134.         MOV     AH,GET_INTERRUPT_VECTOR
  1135.         INT     21H
  1136.         MOV     WORD PTR [REAL_INT_17+2],ES
  1137.         MOV     WORD PTR [REAL_INT_17],BX
  1138.         MOV     AL,14H
  1139.         MOV     AH,GET_INTERRUPT_VECTOR
  1140.         INT     21H
  1141.         MOV     WORD PTR [REAL_INT_14+2],ES
  1142.         MOV     WORD PTR [REAL_INT_14],BX
  1143.         MOV     AL,5H
  1144.         MOV     AH,GET_INTERRUPT_VECTOR
  1145.         INT     21H
  1146.         MOV     WORD PTR [REAL_INT_5+2],ES
  1147.         MOV     WORD PTR [REAL_INT_5],BX
  1148.         PUSH    CS
  1149.         POP     ES
  1150.         MOV     BP,OFFSET DG:LISTFCB + 1
  1151.         MOV     SI,BP
  1152.         MOV     CX,8
  1153. CONLP:                  ;Make sure device name in upper case
  1154.         LODSB
  1155.         CMP     AL,'a'
  1156.         JB      DOCONLP
  1157.         CMP     AL,'z'
  1158.         JA      DOCONLP
  1159.         SUB     BYTE PTR [SI-1],20H
  1160. DOCONLP:
  1161.         LOOP    CONLP
  1162.         MOV     DI,OFFSET DG:INT_17_HITLIST
  1163. CHKHIT:
  1164.         MOV     SI,BP
  1165.         MOV     CL,[DI]
  1166.         INC     DI
  1167.         JCXZ    NOTONHITLIST
  1168.         REPE    CMPSB
  1169.         LAHF
  1170.         ADD     DI,CX           ;Bump to next position without affecting flags
  1171.         MOV     BL,[DI]         ;Get device number
  1172.         INC     DI
  1173.         SAHF
  1174.         JNZ     CHKHIT
  1175.         XOR     BH,BH
  1176.         MOV     [INT_17_NUM],BX
  1177.         MOV     DX,OFFSET DG:INT_17
  1178.         MOV     AL,17H
  1179.         MOV     AH,SET_INTERRUPT_VECTOR
  1180.         INT     21H             ;Set printer interrupt
  1181.         MOV     DX,OFFSET DG:INT_5
  1182.         MOV     AL,5H
  1183.         MOV     AH,SET_INTERRUPT_VECTOR
  1184.         INT     21H             ;Set print screen interrupt
  1185.         JMP     SHORT ALLSET
  1186. NOTONHITLIST:
  1187.         MOV     DI,OFFSET DG:INT_14_HITLIST
  1188. CHKHIT2:
  1189.         MOV     SI,BP
  1190.         MOV     CL,[DI]
  1191.         INC     DI
  1192.         JCXZ    ALLSET
  1193.         REPE    CMPSB
  1194.         LAHF
  1195.         ADD     DI,CX           ;Bump to next position without affecting flags
  1196.         MOV     BL,[DI]         ;Get device number
  1197.         INC     DI
  1198.         SAHF
  1199.         JNZ     CHKHIT2
  1200.         XOR     BH,BH
  1201.         MOV     [INT_14_NUM],BX
  1202.         MOV     DX,OFFSET DG:INT_14
  1203.         MOV     AL,14H
  1204.         MOV     AH,SET_INTERRUPT_VECTOR
  1205.         INT     21H             ;Set RS232 port interrupt
  1206. ALLSET:
  1207.         ENDIF
  1208.  
  1209.         IF      HARDINT
  1210.         MOV     AH,GET_INDOS_FLAG
  1211.         INT     21H
  1212.         MOV     WORD PTR [INDOS+2],ES   ;Get indos flag location
  1213.         MOV     WORD PTR [INDOS],BX
  1214.         MOV     AL,INTLOC
  1215.         MOV     AH,GET_INTERRUPT_VECTOR
  1216.         INT     21H
  1217.         MOV     WORD PTR [NEXTINT+2],ES
  1218.         MOV     WORD PTR [NEXTINT],BX
  1219.         MOV     DX,OFFSET DG:HDSPINT
  1220.         MOV     AL,INTLOC
  1221.         MOV     AH,SET_INTERRUPT_VECTOR
  1222.         INT     21H             ;Set hardware interrupt
  1223.         ENDIF
  1224.  
  1225.         MOV     [MAKERES],1     ;Indicate to do a terminate stay resident
  1226.         MOV     DX,OFFSET DG:GOODMES
  1227.         MOV     AH,STD_CON_STRING_OUTPUT
  1228.         INT     21H
  1229.         RET
  1230.  
  1231. ASSUME  CS:DG,DS:DG,ES:DG,SS:DG
  1232.  
  1233. TRANSIENT:
  1234. ;User interface
  1235.         CLD
  1236.  
  1237. ;Code to print header
  1238. ;       MOV     DX,OFFSET DG:HEADER
  1239. ;       MOV     AH,STD_CON_STRING_OUTPUT
  1240. ;       INT     21H
  1241.  
  1242. DOSVER_LOW      EQU  0136H   ;1.54 in hex
  1243. DOSVER_HIGH     EQU  0200H   ;2.00 in hex
  1244.         MOV     AH,GET_VERSION
  1245.         INT     21H
  1246.         XCHG    AH,AL           ;Turn it around to AH.AL
  1247.         CMP     AX,DOSVER_LOW
  1248.         JB      GOTBADDOS
  1249.         CMP     AX,DOSVER_HIGH
  1250.         JBE     OKDOS
  1251. GOTBADDOS:
  1252.         PUSH    CS
  1253.         POP     DS
  1254.         MOV     DX,OFFSET DG:BADVER
  1255.         MOV     AH,STD_CON_STRING_OUTPUT
  1256.         INT     21H
  1257.         INT     20H
  1258. OKDOS:
  1259.         MOV     AX,CHAR_OPER SHL 8
  1260.         INT     21H
  1261.         MOV     [SWITCHAR],DL           ;Get user switch character
  1262.         MOV     AH,GET_INTERRUPT_VECTOR
  1263.         MOV     AL,COMINT
  1264.         INT     21H
  1265. ASSUME  ES:NOTHING
  1266.         MOV     DI,BX
  1267.         MOV     SI,OFFSET DG:SPCOMINT
  1268.         MOV     CX,13
  1269.         REPE    CMPSB
  1270.         JZ      GOTRES          ;Signature matched
  1271.         PUSH    CS
  1272.         POP     ES
  1273.         CALL    SETUP
  1274. GOTRES:
  1275.         PUSH    CS
  1276.         POP     ES
  1277.         MOV     AH,GET_DEFAULT_DRIVE
  1278.         INT     21H
  1279.         MOV     [DEFDRV],AL
  1280.         MOV     SI,PARMS
  1281.         LODSB
  1282.         OR      AL,AL
  1283.         JNZ     GOTPARMS
  1284. TRANEXIT:
  1285.         CALL    GETSPLIST
  1286.         CMP     [MAKERES],0
  1287.         JNZ     SETRES
  1288.         INT     20H
  1289.  
  1290. SETRES:
  1291.         MOV     DX,[ENDRES]
  1292.         INT     27H
  1293.  
  1294. ARGSDONE:
  1295.         CMP     [ARGSETUP],0
  1296.         JZ      TRANEXIT
  1297.         CALL    PROCESS
  1298.         JMP     SHORT TRANEXIT
  1299.  
  1300. GOTPARMS:
  1301. PARSE:
  1302.         MOV     DI,OFFSET DG:PARSEBUF
  1303.         CALL    CPARSE
  1304.         JC      ARGSDONE
  1305.         CMP     AX,4            ;Switch?
  1306.         JNZ     GOTNORMARG
  1307.         MOV     AL,[DI]         ;Get the switch character
  1308.         CMP     AL,'C'
  1309.         JZ      SETCAN
  1310.         CMP     AL,'c'
  1311.         JNZ     CHKSPL
  1312. SETCAN:
  1313.         MOV     [CANFLG],1
  1314.         JMP     SHORT PARSE
  1315. CHKSPL:
  1316.         CMP     AL,'P'
  1317.         JZ      RESETCAN
  1318.         CMP     AL,'p'
  1319.         JNZ     CHKTERM
  1320. RESETCAN:
  1321.         MOV     [CANFLG],0
  1322.         JMP     SHORT PARSE
  1323. CHKTERM:
  1324.         CMP     AL,'T'
  1325.         JZ      SETTERM
  1326.         CMP     AL,'t'
  1327.         JZ      SETTERM
  1328.         MOV     DX,OFFSET DG:BADSWT
  1329.         MOV     AH,STD_CON_STRING_OUTPUT
  1330.         INT     21H
  1331.         JMP     SHORT PARSE
  1332.  
  1333. SETTERM:
  1334.         CALL    TERMPROCESS
  1335.         JMP     TRANEXIT        ; Ignore everything after T switch
  1336.  
  1337. GOTNORMARG:
  1338.         XOR     AL,AL
  1339.         XCHG    AL,[ARGSETUP]
  1340.         OR      AL,AL
  1341.         JZ      PARSEARG
  1342.         CALL    NORMPROC        ;Don't test ARGSETUP, it just got zeroed
  1343. PARSEARG:
  1344.         PUSH    SI
  1345.         MOV     SI,DI
  1346.         MOV     DI,FCB
  1347.         MOV     AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 1
  1348.         INT     21H             ;Parse the arg
  1349.         CMP     BYTE PTR [DI],0
  1350.         JNZ     DRVOK
  1351.         MOV     DL,[DEFDRV]
  1352.         INC     DL
  1353.         MOV     BYTE PTR [DI],DL        ;Set the default drive
  1354. DRVOK:
  1355.         POP     SI
  1356.         INC     [ARGSETUP]
  1357.         JMP     SHORT PARSE
  1358.  
  1359. TERMPROCESS:
  1360.         MOV     DX,-1
  1361. PROCRET:
  1362.         MOV     AH,1
  1363.         CALL    DOSET
  1364. PROCRETNFUNC:
  1365.         MOV     [ARGSETUP],0
  1366.         PUSH    CS
  1367.         POP     ES
  1368. RET14:  RET
  1369.  
  1370. PROCESS:
  1371.         CMP     [ARGSETUP],0
  1372.         JZ      RET14                   ;Nothing to process
  1373. NORMPROC:
  1374.         MOV     AL,BYTE PTR DS:[FCB+1]
  1375.         CMP     AL," "
  1376.         JZ      SRCHBADJ
  1377.         MOV     DX,FCB
  1378.         MOV     AH,[CANFLG]
  1379.         CMP     AH,0
  1380.         JNZ     PROCRET
  1381.         MOV     DX,OFFSET DG:SRCHFCB
  1382.         MOV     AH,SET_DMA
  1383.         INT     21H
  1384.         MOV     DX,FCB
  1385.         MOV     AH,DIR_SEARCH_FIRST
  1386.         INT     21H
  1387.         OR      AL,AL
  1388.         JNZ     SRCHBADJ
  1389. SRCHLOOP:
  1390.         MOV     DX,OFFSET DG:SRCHFCB
  1391.         MOV     AH,FCB_OPEN
  1392.         INT     21H
  1393.         OR      AL,AL
  1394.         JZ      OPENOK
  1395.         CALL    OPENERR
  1396.         JMP     SHORT NEXTSEARCH
  1397. SRCHBADJ: JMP   SRCHBAD
  1398. OPENOK:
  1399.         MOV     DX,OFFSET DG:SRCHFCB
  1400.         MOV     AH,0
  1401.         CALL    DOSET
  1402.         OR      AL,AL
  1403.         JZ      NEXTSEARCH
  1404.         XCHG    AL,[FULLFLAG]           ;Know AL non-zero
  1405.         OR      AL,AL
  1406.         JNZ     NEXTSEARCH              ;Only print message once
  1407.         MOV     DX,OFFSET DG:FULLMES    ;Queue full
  1408.         MOV     AH,STD_CON_STRING_OUTPUT
  1409.         INT     21H
  1410. NEXTSEARCH:
  1411.         MOV     DX,OFFSET DG:SRCHFCB
  1412.         MOV     AH,SET_DMA
  1413.         INT     21H
  1414.         MOV     DX,FCB
  1415.         MOV     AH,DIR_SEARCH_NEXT
  1416.         INT     21H
  1417.         OR      AL,AL
  1418.         JNZ     PROCRETNFUNC
  1419.         JMP     SRCHLOOP
  1420.  
  1421. DOSET:
  1422.         INT     COMINT
  1423.         MOV     [FILCNT],AH             ;Suck up return info
  1424.         MOV     WORD PTR [SPLIST+2],ES
  1425.         MOV     WORD PTR [CURFILE+2],ES
  1426.         MOV     WORD PTR [SPLIST],BX
  1427.         MOV     WORD PTR [CURFILE],DX
  1428.         RET
  1429.  
  1430. OPENERR:
  1431.         PUSH    SI
  1432.         PUSH    DI
  1433.         MOV     SI,OFFSET DG:OPFILNAM
  1434.         PUSH    DS
  1435.         POP     ES
  1436.         MOV     DI,OFFSET DG:SRCHFCB
  1437.         CALL    MVFNAM
  1438.         MOV     DX,OFFSET DG:OPMES
  1439.         MOV     AH,STD_CON_STRING_OUTPUT
  1440.         INT     21H
  1441.         POP     DI
  1442.         POP     SI
  1443.         RET
  1444.  
  1445. SRCHBAD:
  1446.         PUSH    SI
  1447.         PUSH    DI
  1448.         MOV     SI,OFFSET DG:SRCHFNAM
  1449.         PUSH    DS
  1450.         POP     ES
  1451.         MOV     DI,FCB
  1452.         CALL    MVFNAM
  1453.         MOV     DX,OFFSET DG:SRCHMES
  1454.         MOV     AH,STD_CON_STRING_OUTPUT
  1455.         INT     21H
  1456.         POP     DI
  1457.         POP     SI
  1458.         JMP     PROCRETNFUNC
  1459.  
  1460. GETSPLIST:
  1461.         MOV     AH,0FFH
  1462.         CALL    DOSET
  1463.         PUSH    DS
  1464.         LDS     DI,[SPLIST]
  1465.         MOV     DI,[DI-2]               ;Get the error count
  1466.         POP     DS
  1467.         CMP     DI,ERRCNT1
  1468.         JB      CNTOK
  1469.         MOV     DX,OFFSET DG:CNTMES
  1470.         MOV     AH,STD_CON_STRING_OUTPUT
  1471.         INT     21H
  1472. CNTOK:
  1473.         MOV     CL,[FILCNT]
  1474.         OR      CL,CL
  1475.         JZ      NOFILES
  1476.         XOR     CH,CH
  1477.         LES     DI,[CURFILE]
  1478.         PUSH    DI
  1479.         INC     DI
  1480.         INC     DI
  1481.         MOV     SI,OFFSET DG:CURFNAM
  1482.         CALL    MVFNAM
  1483.         POP     DI
  1484.         MOV     DX,OFFSET DG:CURMES
  1485.         MOV     AH,STD_CON_STRING_OUTPUT
  1486.         INT     21H
  1487.         DEC     CX
  1488.         JCXZ    RET12
  1489. FILOOP:
  1490.         MOV     DI,ES:[DI]
  1491.         PUSH    DI
  1492.         INC     DI
  1493.         INC     DI
  1494.         MOV     SI,OFFSET DG:FILFNAM
  1495.         CALL    MVFNAM
  1496.         POP     DI
  1497.         MOV     DX,OFFSET DG:FILMES
  1498.         MOV     AH,STD_CON_STRING_OUTPUT
  1499.         INT     21H
  1500.         LOOP    FILOOP
  1501. RET12:  RET
  1502.  
  1503. NOFILES:
  1504.         MOV     DX,OFFSET DG:NOFILS
  1505.         MOV     AH,STD_CON_STRING_OUTPUT
  1506.         INT     21H
  1507.         RET
  1508.  
  1509. ;Make a message with the file name
  1510. MVFNAM:
  1511. ASSUME  DS:NOTHING,ES:NOTHING
  1512.         PUSH    SI
  1513.         PUSH    DI
  1514.         PUSH    CX
  1515.         MOV     AX,ES
  1516.         PUSH    DS
  1517.         POP     ES
  1518.         MOV     DS,AX
  1519.         XCHG    SI,DI
  1520.         LODSB
  1521.         ADD     AL,"@"
  1522.         CMP     AL,"@"
  1523.         JNZ     STCHR
  1524.         MOV     AL,[DEFDRV]
  1525.         ADD     AL,"A"
  1526. STCHR:
  1527.         STOSB
  1528.         INC     DI
  1529.         MOV     CX,4
  1530.         REP     MOVSW
  1531.         INC     DI
  1532.         MOVSW
  1533.         MOVSB
  1534.         MOV     AX,ES
  1535.         PUSH    DS
  1536.         POP     ES
  1537.         MOV     DS,AX
  1538.         POP     CX
  1539.         POP     DI
  1540.         POP     SI
  1541.         RET
  1542.  
  1543. ;-----------------------------------------------------------------------;
  1544. ; ENTRY:                                                                ;
  1545. ;       DS:SI   Points input buffer                                     ;
  1546. ;       ES:DI   Points to the token buffer                              ;
  1547. ;                                                                       ;
  1548. ; EXIT:                                                                 ;
  1549. ;       DS:SI   Points to next char in the input buffer                 ;
  1550. ;       ES:DI   Points to the token buffer                              ;
  1551. ;       CX      Character count                                         ;
  1552. ;       AX      Condition Code                                          ;
  1553. ;               =1 same as carry set                                    ;
  1554. ;               =2 normal token                                         ;
  1555. ;               =4 switch character, char in token buffer               ;
  1556. ;       Carry Flag      Set if a CR was found, Reset otherwise          ;
  1557. ;                                                                       ;
  1558. ; MODIFIES:                                                             ;
  1559. ;       CX, SI, AX and the Carry Flag                                   ;
  1560. ;                                                                       ;
  1561. ;-----------------------------------------------------------------------;
  1562.  
  1563. TAB     equ     09h
  1564. CR      equ     0dh
  1565.  
  1566. CPARSE:
  1567. ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING
  1568.         pushf                           ;save flags
  1569.         push    di                      ;save the token buffer addrss
  1570.         xor     cx,cx                   ;no chars in token buffer
  1571.         call    kill_bl
  1572.  
  1573.         cmp     al,CR                   ;a CR?
  1574.         jne     sj2                     ;no, skip
  1575. sj1:
  1576.         mov     ax,1                    ;condition code
  1577.         dec     si                      ;adjust the pointer
  1578.         pop     di                      ;retrive token buffer address
  1579.         popf                            ;restore flags
  1580.         stc                             ;set the carry bit
  1581.         ret
  1582.  
  1583. sj2:
  1584.         mov     dl,[SWITCHAR]
  1585.         cmp     al,dl                   ;is the char the switch char?
  1586.         jne     anum_char               ;no, process...
  1587.         call    kill_bl
  1588.         cmp     al,CR                   ;a CR?
  1589.         je      sj1                     ;yes, error exit
  1590.         call    move_char               ;Put the switch char in the token buffer
  1591.         mov     ax,4                    ;Flag switch
  1592.         jmp     short x_done2
  1593.  
  1594. anum_char:
  1595.         call    move_char               ;just an alphanum string
  1596.         lodsb
  1597.         cmp     al,' '
  1598.         je      x_done
  1599.         cmp     al,tab
  1600.         je      x_done
  1601.         cmp     al,CR
  1602.         je      x_done
  1603.         cmp     al,','
  1604.         je      x_done
  1605.         cmp     al,'='
  1606.         je      x_done
  1607.         cmp     al,dl                   ;Switch character
  1608.         jne     anum_char
  1609. x_done:
  1610.         dec     si                      ;adjust for next round
  1611.         mov     ax,2                    ;normal token
  1612. x_done2:
  1613.         push    ax                      ;save condition code
  1614.         mov     al,0
  1615.         stosb                           ;null at the end
  1616.         pop     ax
  1617.         pop     di                      ;restore token buffer pointer
  1618.         popf
  1619.         clc                             ;clear carry flag
  1620.         ret
  1621.  
  1622.  
  1623. kill_bl proc    near
  1624.         lodsb
  1625.         cmp     al,' '
  1626.         je      kill_bl
  1627.         cmp     al,tab
  1628.         je      kill_bl
  1629.         cmp     al,','                  ;a comma?
  1630.         je      kill_bl
  1631.         cmp     al,'='
  1632.         je      kill_bl
  1633.         ret
  1634. kill_bl endp
  1635.  
  1636.  
  1637. move_char proc  near
  1638.         stosb                           ;store char in token buffer
  1639.         inc     cx                      ;increment char count
  1640.         ret
  1641. move_char endp
  1642.  
  1643. CODE    ENDS
  1644.         END     START
  1645.